<template>
  <div id="demo2" class="containers app-container home" ref="content">
    <ul class="buttons">
      <li>
        <el-button type="success" @click="open = true" v-if="btnShowType">保存</el-button>
        <el-button type="success" @click="handleBlank" class="btn-blank" v-else>返回</el-button>
      </li>
    </ul>
    <div class="canvas" ref="canvas"></div>
    <panel v-if="bpmnModeler" :modeler="bpmnModeler" />
    <el-dialog title="流程信息" :visible.sync="open" width="30%" center>
      <el-form :model="dialogForm" ref="numberValidateForm" label-width="100px" class="demo-ruleForm">
        <el-form-item label="流程名称" prop="name" :rules="[{ required: true, message: '流程名称不能为空！' }]">
          <el-input v-model="dialogForm.name"></el-input>
        </el-form-item>
        <el-form-item label="流程描述" prop="description">
          <el-input v-model="dialogForm.description"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="open = false" class="dialogCancel">取 消</el-button>
        <el-button type="primary" @click="saveXmlFile" class="tableAdd">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
// 引入相关的依赖
import BpmnModeler from "bpmn-js/lib/Modeler";
import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/camunda";
import panel from "./PropertyPanel"; // 属性面板
import { addProcess, details } from "@/api/approvalManage/processManage.js";
import BpmData from "./BpmData";
export default {
  data() {
    return {
      // bpmn建模器
      bpmnModeler: null,
      container: null,
      canvas: null,
      xmlStr: null,
      processName: "",
      svgXml: "",
      bpmData: new BpmData(),
      open: false,
      dialogForm: {
        name: "",
        description: "",
      },
      detailsXml: null,
      btnShowType: true,
      editId: null
    };
  },
  components: {
    panel,
  },
  methods: {
    createNewDiagram() {
      const bpmnXmlStr = this.detailsXml
        ? this.detailsXml
        : `
      <?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="sid-38422fae-e03e-43a3-bef4-bd33b32041b2" targetNamespace="http://bpmn.io/bpmn" exporter="bpmn-js (https://demo.bpmn.io)" exporterVersion="10.2.0">
  <process id="${this.$route.query.processKey}" isExecutable="true">
    <startEvent id="Event_0z2ugqg">
      <outgoing>Flow_0ux38yw</outgoing>
    </startEvent>
  </process>
  <bpmndi:BPMNDiagram id="BpmnDiagram_1">
    <bpmndi:BPMNPlane id="BpmnPlane_1" bpmnElement="Process_1">
      <bpmndi:BPMNShape id="Event_0z2ugqg_di" bpmnElement="Event_0z2ugqg">
        <omgdc:Bounds x="152" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1qwhgqv_di" bpmnElement="Activity_1qwhgqv">
        <omgdc:Bounds x="240" y="80" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_0vdn4x2_di" bpmnElement="Activity_0vdn4x2">
        <omgdc:Bounds x="400" y="80" width="100" height="80" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_0h9gag3_di" bpmnElement="Event_0h9gag3">
        <omgdc:Bounds x="562" y="102" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_0ux38yw_di" bpmnElement="Flow_0ux38yw">
        <omgdi:waypoint x="188" y="120" />
        <omgdi:waypoint x="240" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0ib1da8_di" bpmnElement="Flow_0ib1da8">
        <omgdi:waypoint x="340" y="120" />
        <omgdi:waypoint x="400" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_11r2sgt_di" bpmnElement="Flow_11r2sgt">
        <omgdi:waypoint x="500" y="120" />
        <omgdi:waypoint x="562" y="120" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
`;
      const _this = this;
      // 将字符串转换成图显示出来
      this.bpmnModeler.importXML(bpmnXmlStr, function (err) {
        if (err) {
          console.error(err);
        } else {
          _this.adjustPalette();
        }
      });
    },
    // 调整左侧工具栏排版
    adjustPalette() {
      try {
        // 获取 bpmn 设计器实例
        const canvas = this.$refs.canvas;

        const djsPalette = canvas.children[0].children[1].children[4];
        const djsPalStyle = {
          width: "500px",
          padding: "5px",
          background: "white",
          borderRadius: 0,
        };
        for (var key in djsPalStyle) {
          djsPalette.style[key] = djsPalStyle[key];
        }
        const palette = djsPalette.children[0];
        const allGroups = palette.children;
        allGroups[0].style["display"] = "none";
        // 修改控件样式
        for (var gKey in allGroups) {
          const group = allGroups[gKey];
          for (var cKey in group.children) {
            const control = group.children[cKey];
            const controlStyle = {
              display: "flex",
              justifyContent: "flex-start",
              alignItems: "center",
              width: "23%",
              padding: "5px",
            };
            if (
              control.className &&
              control.dataset &&
              control.className.indexOf("entry") !== -1
            ) {
              const controlProps = this.bpmData.getControl(
                control.dataset.action
              );
              control.innerHTML = `<div style='font-size: 14px;font-weight:500;margin-left:15px;'>${controlProps["title"]}</div>`;
              if (controlProps["tooltip"]) {
                control.title = controlProps["tooltip"];
              }
              for (var csKey in controlStyle) {
                control.style[csKey] = controlStyle[csKey];
              }
            }
          }
        }
      } catch (e) {
        console.log(e);
      }
    },
    // 下载为SVG格式,done是个函数，调用的时候传入的
    saveSVG(done) {
      // 把传入的done再传给bpmn原型的saveSVG函数调用
      this.bpmnModeler.saveSVG(done);
    },
    // 下载为SVG格式,done是个函数，调用的时候传入的
    saveDiagram(done) {
      // 把传入的done再传给bpmn原型的saveXML函数调用
      this.bpmnModeler.saveXML({ format: true }, function (err, xml) {
        done(err, xml);
      });
    },
    // 当图发生改变的时候会调用这个函数，这个data就是图的xml
    setEncoded(link, name, data) {
      // 把xml转换为URI，下载要用到的
      const encodedData = encodeURIComponent(data);
      // 获取到图的xml，保存就是把这个xml提交给后台
      this.xmlStr = data;
      // 下载图的具体操作,改变a的属性，className令a标签可点击，href令能下载，download是下载的文件的名字
    },
    // 保存整个XML文件
    saveXmlFile() {
      const params = {
        id: this.editId ? this.editId : this.$route.query.data,
        jsonXml: this.xmlStr,
        svgXml: this.svgXml,
        name: this.dialogForm.name,
        description: this.dialogForm.description,
      };
      addProcess(params).then((res) => {
        this.$message.success("操作成功！");
        this.$router.push({
          path: "/approvalManage/processManage",
        });
      });
    },
    handleModeler() {
      // 监听节点选择变化
      this.bpmnModeler.on("selection.changed", (e) => {
        const element = e.newSelection[0];
        this.element = element;
        if (!element) return true;
      });

      //  监听节点属性变化
      this.bpmnModeler.on("element.changed", (e) => {
        const { element } = e;
        if (!element) return true;
      });

      // 自定义事件
      let eventBus = this.bpmnModeler.get("eventBus");
      let that = this;
      eventBus.on("element.dblclick", function (e) {
        that.element = e.element;
      });
    },
    // 详情接口
    initDetails() {
      const data = JSON.parse(this.$route.query.data);
      console.log(data)
      this.editId = data.id;
      const params = {
        modelId: data.modelId,
      };
      details(params).then((res) => {
        this.detailsXml = res.data.json.replace(
          /activiti:candidateUsers/g,
          "candidateUsers"
        );
        this.xmlStr = this.detailsXml;
        this.svgXml = res.data.svgXml;
        this.dialogForm.name = res.data.modelNode.name;
        this.dialogForm.description = res.data.modelNode.description;
        this.createNewDiagram(this.bpmnModeler);
      });
    },
    // 返回列表页
    handleBlank() {
      this.$router.push({
        path: "/approvalManage/processManage",
      });
    },
  },
  mounted() {
    // 获取到属性ref为“content”的dom节点
    this.container = this.$refs.content;
    // 获取到属性ref为“canvas”的dom节点
    const canvas = this.$refs.canvas;

    // 建模，官方文档这里讲的很详细
    this.bpmnModeler = new BpmnModeler({
      container: canvas,
      // 添加控制板
      propertiesPanel: {
        parent: "#js-properties-panel",
      },
      additionalModules: [
        // 左边工具栏以及节点
        propertiesProviderModule,
        // 右边的工具栏
        // propertiesPanelModule
      ],
    });

    // 下载画图
    let _this = this;
    // 获取a标签dom节点
    const downloadLink = this.$refs.saveDiagram;
    const downloadSvgLink = this.$refs.saveSvg;
    // 给图绑定事件，当图有发生改变就会触发这个事件
    this.bpmnModeler.on("commandStack.changed", function () {
      _this.saveSVG(function (err, svg) {
        _this.svgXml = svg;
        _this.setEncoded(downloadSvgLink, "diagram.svg", err ? null : svg);
      });

      _this.saveDiagram(function (err, xml) {
        _this.setEncoded(downloadLink, "diagram.bpmn", err ? null : xml);
      });
    });
    if (this.$route.query.type === "details" || this.$route.query.type === "edit") {
      this.btnShowType = this.$route.query.type === "details" ? false : true;
      this.initDetails();
    } else {
      this.createNewDiagram(this.bpmnModeler);
    }
    this.handleModeler();
  },
};
</script>

<style scoped lang="scss">
/*左边工具栏以及编辑节点的样式*/
@import "~bpmn-js/dist/assets/diagram-js.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";

/*右边工具栏样式*/
/* @import "bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css"; */
.containers {
  position: relative;
  background-color: #ffffff;
  width: 100%;
}

.canvas {
  width: 100%;
  height: 100%;
}

.canvas>div>a {
  display: none;
}

.panel {
  position: absolute;
  right: 0;
  top: 0;
  width: 300px;
}

.buttons {
  position: absolute;
  top: 20px;
  right: 0;
  z-index: 999;
}

::v-deep .el-button--success {
  background: #971111;
  border-color: #971111;
  color: #fff;

  &:hover {
    background: #971111;
    border-color: #971111;
  }

  &:focus {
    background: #971111;
    border-color: #971111;
  }
}

.buttons>li {
  display: inline-block;
  margin-right: 320px;
}

.buttons>li>a {
  color: #999;
  background: #eee;
  cursor: not-allowed;
  padding: 8px;
  border: 1px solid #ccc;
}

.buttons>li>a.active {
  color: #333;
  background: #fff;
  cursor: pointer;
}

::v-deep .bpmn-icon-intermediate-event-none,
::v-deep .bpmn-icon-gateway-none,
::v-deep .bpmn-icon-task,
::v-deep .bpmn-icon-subprocess-expanded,
::v-deep .bpmn-icon-data-object,
::v-deep .bpmn-icon-data-store,
::v-deep .bpmn-icon-participant,
::v-deep .bpmn-icon-group,
::v-deep .bjs-powered-by {
  display: none !important;
}

::v-deep .djs-palette {
  border: none;
  left: 0;
  top: 0;

  .bpmn-icon-start-event-none {
    &::before {
      color: #971111;
    }
  }

  .bpmn-icon-end-event-none {
    &::before {
      color: #971111;
    }
  }

  .bpmn-icon-user-task {
    &::before {
      color: #971111;
    }
  }
}

.btn-blank {
  background: #fff;
  border: 1px solid #971111;
  color: #971111;

  &:hover {
    background: #fff;
    border: 1px solid #971111;
    color: #971111;
  }

  &:focus {
    background: #fff;
    border: 1px solid #971111;
    color: #971111;
  }
}
</style>
